package fem2.pre_and_post;

import inf.jlinalg.IVector;

import java.io.IOException;
import java.io.Writer;

import fem2.Element;
import fem2.Mesh;
import fem2.Model;
import fem2.Node;
import fem2.element.PoissonElement;

/**
 * class to write post-processing file for GID
 * 
 * @author hbui
 * 
 */
public class GidPostForPoissonProblem extends GidPost {

	public GidPostForPoissonProblem(String projectGidDir, String projectName) {
		super(projectGidDir, projectName);
	}

	public GidPostForPoissonProblem(String projectGidDir, String projectName, String fileName) {
		super(projectGidDir, projectName, fileName);
	}

	/**
	 * write displacement results to nodes. This method is exclusive
	 * 
	 * @param an
	 * @param timeStep
	 * @throws IOException
	 */
	public void writeNodalTemperatureResults(Model m, double timeStep) throws IOException {
		Writer output = createWriter(timeStep);
		output.write("Result ");
		output.write('"' + "TEMPERATURE" + '"' + " ");
		output.write('"' + "fem2012 analysis" + '"' + " ");
		output.write(timeStep + " ");
		output.write("Scalar ");
		output.write("OnNodes\n");
		output.write("Values\n");

		Mesh mesh = m.getMesh();
		for (int i = 0; i < mesh.countNodes(); i++) {
			Node node = mesh.getNode(i);
			double[] u = node.getUHatLocal();
			output.write(node.getId() + " " + u[0] + " \n");
		}

		output.write("End Values\n");
		output.close();

		System.out.println("Write nodal temperatures completed");
	}

	/**
	 * write stress at each Gauss point to Gid post file.
	 * 
	 * @param m
	 * @param timeStep
	 * @param checkPrinciple
	 * @throws IOException
	 */
	public void writeGaussPointHeatFluxResults(Model m, double timeStep) throws IOException {
		for (String elemType : m.getElementTypes()) {
			/*
			 * extract one element of elemType
			 */
			Element e = null;
			for (int i = 0; i < m.countElements(); i++) {
				if (m.getElement(i).getElemType().equals(elemType)) {
					e = m.getElement(i);
					break;
				}
			}
			/*
			 * extract number of Gauss point
			 */
			if (e == null) {
				throw new Error("element type " + elemType + " does not exist in the model");
			} else {
				int ng = e.getNumIntegrationPoints();
				writeGaussPointHeatFluxResults(m, elemType, ng, timeStep);
			}
		}
		System.out.println("Write heat flux at Gauss point completed");
	}

	/**
	 * write stress at each Gauss point to Gid post file for a specific type of
	 * element and Gauss point
	 * 
	 * @param m
	 * @param elementType
	 * @param ng
	 * @param timeStep
	 * @param checkPrinciple
	 * @throws IOException
	 */
	private void writeGaussPointHeatFluxResults(Model m, String elementType, int ng, double timeStep)
			throws IOException {
		Writer output = createWriter(timeStep);
		int dim = m.getMesh().getDimension();
		String groupName = elementType + "_heat_flux_gp";
		/*
		 * write declaration for GaussPoints block
		 */
		output.write("GaussPoints ");
		output.write('"' + groupName + '"' + " ");
		output.write("ElemType ");
		output.write(elementType + "\n");
		output.write("Number Of Gauss Points: " + ng + "\n");
		output.write("Natural Coordinates: Internal\n");
		output.write("End GaussPoints\n");
		/*
		 * write block of result declaration
		 */
		output.write("Result ");
		output.write('"' + "HEAT_FLUX_VECTOR" + '"' + " ");
		output.write('"' + "fem2012 analysis" + '"' + " ");
		output.write(timeStep + " ");
		output.write("Vector ");
		output.write("OnGaussPoints ");
		output.write('"' + groupName + '"' + "\n");
		output.write("Values\n");
		/*
		 * write data
		 */
		for (int i = 0; i < m.countElements(); i++) {
			PoissonElement e = (PoissonElement) m.getElement(i);
			if (e.getElemType().equals(elementType)) {
				output.write(e.getId() + " ");
				int[] map = getGaussPointMapping(elementType, ng);
				for (int k = 0; k < ng; k++) {
					IVector heat_flux;

					heat_flux = e.getHeatFlux(map[k] - 1);

					/*
					 * write heat flux
					 */
					if (dim == 2) {
						output.write(heat_flux.get(0) + " " + heat_flux.get(1) + " " + " 0 \n");
					} else if (dim == 3) {
						output.write(heat_flux.get(0) + " " + heat_flux.get(1) + " "
								+ heat_flux.get(2) + "\n");
					}
				}
			}
		}
		/*
		 * end
		 */
		output.write("End Values\n");

		/*
		 * close
		 */
		output.close();
	}

}
